package cn.edu.sdjzu.xg.eagle.dao.mapper;

import cn.edu.sdjzu.xg.eagle.dao.UserDao;
import cn.edu.sdjzu.xg.eagle.entity.Actor;
import cn.edu.sdjzu.xg.eagle.entity.ActorType;
import cn.edu.sdjzu.xg.eagle.entity.User;
import cn.edu.sdjzu.xg.eagle.exception.BaseException;
import cn.edu.sdjzu.xg.eagle.factory.ServiceFactory;
import cn.edu.sdjzu.xg.eagle.service.TeacherService;
import cn.edu.sdjzu.xg.eagle.util.JdbcHelper;

import java.lang.reflect.InvocationTargetException;
import java.sql.*;


public final class UserDaoImpl implements UserDao {

//    public User findWithActor(Connection connection, int id) throws SQLException, InvocationTargetException {
//        //先后在Sudent和Teacher中查找相应的id
//        User desiredUser = this.find(connection, id);
//        switch (desiredUser.getActorType()) {
//            case TEACHER:
//                // 调用TeacherService的find方法，返回Teacher类型的Actor
//                Teacher teacher = ServiceFactory.getService(TeacherService.class, "TeacherServiceImpl")
//                        .find(connection, desiredUser.getActor().getId());
//                desiredUser.setActor(teacher);
//                break;
//            case STUDENT:
//                // 返回Student类型的Actor
//                break;
//            //出现了其它类型
//            default:
//                break;
//        }
//        return desiredUser;
//    }

        @Override
        public User find (Connection connection, Integer id)
                throws SQLException, BaseException, InvocationTargetException {
            if (connection == null) {
                throw new IllegalArgumentException("数据库连接为空");
            }
            if (id == null) {
                throw new IllegalArgumentException("id为空");
            }
            //声明User类型的引用，暂不创建对象
            User desiredUser = null;
            String sql_select_id = "SELECT * from bysj22.user WHERE id = ?";
            PreparedStatement pstmt_select_id = connection.prepareStatement(sql_select_id);
            pstmt_select_id.setInt(1, id);
            ResultSet resultSet_select_id = pstmt_select_id.executeQuery();
            //如果User表中存在参数id对应的记录，则获得表中的字段值，并创建User对象
            if (resultSet_select_id.next()) {
                String username = resultSet_select_id.getString("username");
                String password = resultSet_select_id.getString("password");
                //获得User表中字串类型的actor_type，代表当前User对象实际关联是Actor的哪个子类
                String actorType_str = resultSet_select_id.getString("actor_type");
                //根据子类类型字串，得到相应的枚举常量
                ActorType actorType = ActorType.valueOf(actorType_str);
                //获得外键actor_id的值，它代表User对象关联的Actor子类对象的id
                Long actorId = resultSet_select_id.getLong("actor_id");
                //声明超类类型的引用，以便可以指向任何一种子类的对象
                Actor actor = null;
                {
                    switch (actorType) {
                        //如果关联的是Teacher对象
                        case TEACHER:
                            // 调用TeacherService的find方法，返回Teacher类型的对象，给actor赋值
                            actor = ServiceFactory.getService(TeacherService.class, "TeacherServiceImpl")
                                    .find(connection, actorId);
                            break;
                        case STUDENT:
                            // 调用StudentService的find方法，返回Student类型的对象，给actor赋值
                            break;
                        //出现了其它类型，抛出异常
                        default:
                            throw new BaseException("Unknown actor type: " + actorType);
                    }
                }
                //创建User对象，前4个参数是自身属性，actor关联属性，它指向Actor子类的一个对象
                desiredUser = new User(id, username, password,actorType, actor);
            }
            //关闭Statement和结果集
            JdbcHelper.close(resultSet_select_id, pstmt_select_id);
            return desiredUser;
        }


    //不返回user， 修改它的id是
    @Override
    public void login (Connection connection, User user) throws SQLException {
        //需要异常处理
        connection.setAutoCommit(false);
        String sql_login = "SELECT * from bysj22.user WHERE username =? and password=?";
        String sql_updateLoginTime = "UPDATE bysj22.user SET loginTime = CURRENT_TIMESTAMP WHERE id = ?";
        PreparedStatement pstmt_login =
                connection.prepareStatement(sql_login);
        PreparedStatement pstmp_updateLoginTime = connection.prepareStatement(sql_updateLoginTime);
        pstmt_login.setString(1, user.getUsername());
        pstmt_login.setString(2, user.getPassword());
        ResultSet resultSet_login = pstmt_login.executeQuery();
        //如果表中存在id对应的记录，则获得表中的user_id，并获得对应的User对象
        if (resultSet_login.next()) {
            int user_id = resultSet_login.getInt("id");
            //写入id，Controller中认为User对象拥有id，即为合法用户
            user.setId(user_id);
            pstmp_updateLoginTime.setInt(1, user_id);
            pstmp_updateLoginTime.executeUpdate();
        }
        connection.setAutoCommit(true);
    }


        /**
         * 根据用户名查找
         * @param username 要查找的用户名
         * @return 符合条件的对象
         * @throws SQLException
         */

//    public User findByName(String username) throws SQLException {
//        User desiredUser = null;
//        Connection connection = JdbcHelper.getConn();
//        PreparedStatement preparedStatement =
//                connection.prepareStatement("SELECT * FROM user WHERE username=?");
//        preparedStatement.setString(1,username);
//        ResultSet resultSet = preparedStatement.executeQuery();
//        if(resultSet.next()){
//            int id = resultSet.getInt("id");
//            String password = resultSet.getString("password");
//            Timestamp timestamp = resultSet.getTimestamp("lastLoginTime");
//            LocalDateTime lastLoginTime = null;
//            if(timestamp!=null) {
//                lastLoginTime = timestamp.toLocalDateTime();
//            }
//            int teacherId = resultSet.getInt("teacher_id");
//            Teacher teacherOfUser = TeacherDao.getInstance().find(teacherId, connection);
//            //以当前元组的各个字段值为参数，创建User对象
//            desiredUser =
//                    new User(id,username,password,lastLoginTime);
//        }
//        return desiredUser;
//    }

        /**
         *
         * 两次对Dao的调用要保证是同一Connection对象，才能将它们设置在同一事务中
         * @param user 要增加到数据库表中的User对象
         * @param connection 来自Service的Connection对象
         * @return 成功修改true，失败：false
         * @throws SQLException
         */
        @Override
        public boolean update (Connection connection, User user) throws SQLException {
            //根据连接对象准备语句对象，如果SQL语句为多行，注意语句不同部分之间要有空格
            //创建语句对象, 字段lastLoginTime 为“时间戳”类型，无须手动写入
            PreparedStatement pstmt =
                    connection.prepareStatement("UPDATE bysj.user SET username = ?, password = ?, " +
                            "actor_id = ? WHERE id = ?");
            pstmt.setObject(1, user.getUsername());
            pstmt.setObject(2, user.getPassword());
            pstmt.setObject(3, user.getActor().getId());
            pstmt.setInt(4, user.getId());
            //执行预编译语句，用其返回值、影响的行数为赋值affectedRowNum
            int affectedRowNum = pstmt.executeUpdate();
            //本方法是事务的一部分，不能释放数据库连接
            JdbcHelper.close(pstmt);
            //如果影响记录条数大于0,则表示成功
            return affectedRowNum > 0;
        }


        /**
         * TeacherService.add在调用本方法之前，还会调用TeacherDao.add方法
         * 两次对Dao的调用要保证是同一Connection对象，才能将它们设置在同一事务中
         * @param user 要增加到数据库表中的User对象
         * @param connection 来自Service的Connection对象
         * @return 新增记录的id
         * @throws SQLException
         */
        @Override
        public int add (Connection connection, User user) throws SQLException {

            // 创建User时，不可能有关联的Actor对象，故INSERT语句无须包含相关信息
            // 根据连接对象准备语句对象，如果SQL语句为多行，注意语句不同部分之间要有空格
            // 创建语句对象, 字段lastLoginTime 为“时间戳”类型，无须手动写入
            // 参数Statement.RETURN_GENERATED_KEYS表示执行语句会返回数据库生成的id
            PreparedStatement pstmt =
                    connection.prepareStatement("INSERT INTO bysj22.user  " +
                            "(username, password, actor_type, actor_id) " +
                            "VALUES(?,?,?,?)", Statement.RETURN_GENERATED_KEYS);

            pstmt.setObject(1, user.getUsername());
            pstmt.setObject(2, user.getPassword());
            //枚举类型的属性，需要调用它的name方法才能得到对应的字串
            pstmt.setObject(3, user.getActorType().name());
            pstmt.setObject(4, user.getActor().getId());

            //要求返回新加元组的主键
            //执行预编译语句，用其返回值、影响的行数为赋值affectedRowNum
            int affectedRowNum = pstmt.executeUpdate();
            int idOfAddedUser = 0;
            ResultSet resultSet = pstmt.getGeneratedKeys();//获得生成的主键集合
            if (resultSet.next()) {
                idOfAddedUser = resultSet.getInt(1);//读取第一个主键
            }
            //本方法是事务的一部分，不能释放数据库连接
            JdbcHelper.close(pstmt);
            //新增元组的id
            return idOfAddedUser;
        }
    }
    /**
     * 根据用户名查找
     * @param username 要查找的用户名
     * @return 符合条件的对象
     * @throws SQLException
     */
    
//    public User findByName(String username) throws SQLException {
//        User desiredUser = null;
//        Connection connection = JdbcHelper.getConn();
//        PreparedStatement preparedStatement =
//                connection.prepareStatement("SELECT * FROM user WHERE username=?");
//        preparedStatement.setString(1,username);
//        ResultSet resultSet = preparedStatement.executeQuery();
//        if(resultSet.next()){
//            int id = resultSet.getInt("id");
//            String password = resultSet.getString("password");
//            Timestamp timestamp = resultSet.getTimestamp("lastLoginTime");
//            LocalDateTime lastLoginTime = null;
//            if(timestamp!=null) {
//                lastLoginTime = timestamp.toLocalDateTime();
//            }
//            int teacherId = resultSet.getInt("teacher_id");
//            Teacher teacherOfUser = TeacherDao.getInstance().find(teacherId, connection);
//            //以当前元组的各个字段值为参数，创建User对象
//            desiredUser =
//                    new User(id,username,password,lastLoginTime);
//        }
//        return desiredUser;
//    }
    /**
     *  用户名的基础部分在user表中存的情况下，调用本方法
//    * @param username 用户名的基础部分，如:lkq
//    * @return 用户名的基础部分+序号（整体用户名不存在），如:lkq5
//    * @throws SQLException
//    */
//    public String generateUsername(String username)throws SQLException {
//        //序列号初值为1
//        int usernameSN = 1;
//        //将参数和序列号连接起来，到表中查询
//        while(this.findByName(username+usernameSN)!=null){
//            usernameSN++;
//        }
//        return username + usernameSN;
//    }
//
//
//    public boolean delete(Integer id) throws SQLException {
//        User user = this.find(id);
//        return this.delete(user);
//    }
//
//
//    public boolean delete(User user) throws SQLException {
//        return users.remove(user);
//    }




//    @Override
//    public User login(Connection connection, User user) throws SQLException {
//        User currentUser = null;
//        String sql_login = "SELECT * FROM user WHERE username =? and password=?";
//        PreparedStatement pstmt_login =
//                connection.prepareStatement(sql_login);
//        pstmt_login.setString(1, user.getUsername());
//        pstmt_login.setString(2, user.getPassword());
//        ResultSet resultSet_login = pstmt_login.executeQuery();
//        //如果表中存在id对应的记录，则获得表中的user_id，并获得对应的User对象
//        if (resultSet_login.next()) {
//            int user_id = resultSet_login.getInt("user_id");
//            currentUser = UserService.getInstance().find(user_id);
//        }
//        return currentUser;
//    }


